<template>
  <div
    style="width: 100%; height: 100%"
    class="canvas-container"
    @mousedown.stop
    @dragover.stop.prevent
    @drop.stop.prevent
    @wheel.stop.prevent
    :style="{ backgroundColor: backgroundColor }"
  >
    <canvas
      style="vertical-align: top; width: 100%; height: 100%"
      ref="canvasRef"
      @mousedown="startDragging"
      @mousemove="onDragging"
      @mouseup="stopDragging"
      @mouseleave="stopDragging"
      @wheel.prevent="onWheel"
      @dblclick="onCanvasClick"
    ></canvas>
    <!-- <div class="coordinates"> 坐标: X: {{ markerPosition.x }}, Y: {{ markerPosition.y }} </div> -->
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, defineEmits } from 'vue'
import markerIconUrl from '@/assets/task/point.svg'
import markerOtherIconUrl from '@/assets/task/point_yellow.svg'

const props = withDefaults(
  defineProps<{
    modelValue?: any
    otherPoints?: any[]
    isPreview?: boolean
    monitorDevice: any
    backgroundColor?: string
    pointsFontColor?: string
    pointsFontSize?: number
  }>(),
  {
    otherPoints: () => [], // 设置默认值为 []
    backgroundColor: '#fff',
    pointsFontColor: '#ffff00',
    pointsFontSize: 10
  }
)

const emit = defineEmits<{
  (e: 'update:modelValue', value: any): void
}>()

const isReady = ref(false)

const canvasRef = ref<HTMLCanvasElement | null>(null)
const ctx = ref<CanvasRenderingContext2D | null>(null)
const image = new Image()
image.src = props.monitorDevice.devicePic || '/img-picker.png'

const scale = ref(1)
const offsetX = ref(0)
const offsetY = ref(0)
const isDragging = ref(false)
const dragStart = ref({ x: 0, y: 0 })
const markerPosition = ref()

const markerIcon = new Image()
markerIcon.src = markerIconUrl

const markerOtherIcon = new Image()
markerOtherIcon.src = markerOtherIconUrl

const startDragging = (e: MouseEvent) => {
  isDragging.value = true
  dragStart.value = { x: e.offsetX, y: e.offsetY }
}

const onDragging = (e: MouseEvent) => {
  if (isDragging.value) {
    const dx = e.offsetX - dragStart.value.x
    const dy = e.offsetY - dragStart.value.y

    let newOffsetX = offsetX.value + dx
    let newOffsetY = offsetY.value + dy

    const scaledWidth = image.width * scale.value
    const scaledHeight = image.height * scale.value
    const canvasWidth = canvasRef.value!.width
    const canvasHeight = canvasRef.value!.height

    // 保证四个方向都至少能看到 20px 的图片
    // 右边界（图片右边缘）≥ 20
    if (newOffsetX + scaledWidth < 20) {
      newOffsetX = 20 - scaledWidth
    }

    // 左边界（图片左边缘）≤ canvasWidth - 20
    if (newOffsetX > canvasWidth - 20) {
      newOffsetX = canvasWidth - 20
    }

    // 下边界（图片下边缘）≥ 20
    if (newOffsetY + scaledHeight < 20) {
      newOffsetY = 20 - scaledHeight
    }

    // 上边界（图片上边缘）≤ canvasHeight - 20
    if (newOffsetY > canvasHeight - 20) {
      newOffsetY = canvasHeight - 20
    }

    offsetX.value = newOffsetX
    offsetY.value = newOffsetY
    dragStart.value = { x: e.offsetX, y: e.offsetY }
    draw()
  }
}

const stopDragging = () => {
  isDragging.value = false
}

const onWheel = (e: WheelEvent) => {
  const zoom = e.deltaY < 0 ? 1.1 : 0.9
  const newScale = scale.value * zoom
  // 限制缩放范围
  const clampedScale = Math.max(0.1, Math.min(newScale, 10))

  // 获取鼠标相对于canvas的坐标
  const mouseX = e.offsetX
  const mouseY = e.offsetY

  // 获取鼠标相对于图片的坐标（缩放前）
  const imgX = (mouseX - offsetX.value) / scale.value
  const imgY = (mouseY - offsetY.value) / scale.value

  // 更新偏移量，保持缩放中心为鼠标点
  offsetX.value = mouseX - imgX * clampedScale
  offsetY.value = mouseY - imgY * clampedScale

  scale.value = clampedScale
  draw()
}
const onCanvasClick = (e: MouseEvent) => {
  if (props.isPreview) return
  // 将点击位置转换为图片内的坐标
  const x = (e.offsetX - offsetX.value) / scale.value
  const y = (e.offsetY - offsetY.value) / scale.value

  markerPosition.value = { x: Math.round(x), y: Math.round(y) }
  emit('update:modelValue', {
    ...props.modelValue,
    positionX: markerPosition.value.x.toString(),
    positionY: markerPosition.value.y.toString(),
    positionZ: props.modelValue.positionZ
  })
  draw()
}

const drawMarker = (marker: any, isMain: boolean) => {
  if (!ctx.value) return
  const markerScreenX = marker.positionX * scale.value + offsetX.value
  const markerScreenY = marker.positionY * scale.value + offsetY.value
  // 绘制图标
  ctx.value.drawImage(
    isMain ? markerIcon : markerOtherIcon,
    markerScreenX - 10,
    markerScreenY - 10,
    20,
    20
  )

  // 文本和背景
  const text = marker.name || '点位'
  ctx.value.font = `${props.pointsFontSize * 2}px sans-serif`
  const textWidth = ctx.value.measureText(text).width
  // const bgPadding = 4

  // const bgX = markerScreenX - textWidth / 2 - bgPadding
  // const bgY = markerScreenY - 35
  // const bgWidth = textWidth + bgPadding * 2
  // const bgHeight = 20

  // ctx.value.fillStyle = 'rgba(255, 255, 255, 0.8)'
  // ctx.value.fillRect(bgX, bgY, bgWidth, bgHeight)

  ctx.value.fillStyle = isMain ? 'red' : props.pointsFontColor
  ctx.value.textBaseline = 'middle'
  ctx.value.fillText(text, markerScreenX - textWidth / 2, markerScreenY - 30)
}

const draw = () => {
  if (!ctx.value || !canvasRef.value) return
  ctx.value.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)
  ctx.value.save()
  ctx.value.translate(offsetX.value, offsetY.value)
  ctx.value.scale(scale.value, scale.value)
  ctx.value.drawImage(image, 0, 0)
  ctx.value.restore()

  // 绘制当前 marker
  if (markerPosition.value && markerPosition.value.x && markerPosition.value.y) {
    drawMarker(
      {
        positionX: markerPosition.value.x,
        positionY: markerPosition.value.y,
        name: props.modelValue.name
      },
      true
    )
  }

  // 绘制 otherPoints
  props.otherPoints.forEach((otherPoint) => {
    const p = otherPoint.data.measureData
    if (p.positionX && p.positionY) {
      drawMarker(
        { positionX: Number(p.positionX), positionY: Number(p.positionY), name: p.name },
        false
      )
    }
  })
}

// 监听 modelValue 的变化
watch(
  () => props.modelValue,
  (val) => {
    if (val) {
      markerPosition.value = {
        x: Number(val.positionX) || 0,
        y: Number(val.positionY) || 0
      }
      if (isReady.value) {
        draw()
      }
    }
  },
  { deep: true, immediate: true }
)

watch(
  () => [props.otherPoints, props.pointsFontColor, props.pointsFontSize],
  () => {
    if (isReady.value) {
      draw()
    }
  },
  { immediate: true, deep: true }
)

// 初始化渲染
onMounted(async () => {
  await nextTick()
  if (canvasRef.value) {
    ctx.value = canvasRef.value.getContext('2d')
    canvasRef.value.width = canvasRef.value!.clientWidth
    canvasRef.value.height = canvasRef.value!.clientHeight
    image.onload = () => {
      // 初始化偏移量为居中
      const canvasWidth = canvasRef.value!.width
      const canvasHeight = canvasRef.value!.height

      // 按比例缩放到能完整显示
      const scaleX = canvasWidth / image.width
      const scaleY = canvasHeight / image.height
      scale.value = Math.min(scaleX, scaleY, 1) // 缩放比例（不放大）

      // 更新偏移量，保持居中
      const scaledWidth = image.width * scale.value
      const scaledHeight = image.height * scale.value
      offsetX.value = (canvasWidth - scaledWidth) / 2
      offsetY.value = (canvasHeight - scaledHeight) / 2
      isReady.value = true
      draw()
    }
  }
})
</script>

<style scoped>
.canvas-container {
  /* border: 1px solid #ccc; */
  display: inline-block;
  user-select: none;
}

.coordinates {
  margin-top: 8px;
  font-size: 14px;
}
</style>
